home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / genmix1b.zip / GENMIX / SRC / GENMIX.C next >
C/C++ Source or Header  |  1995-04-15  |  35KB  |  1,465 lines

  1. /*    GENMIX.C -- Generic mixer source code
  2.     (C) Copyright 1995 Ian A. McLean
  3.     See the file README.TXT for license and other information
  4.  
  5.     version 1B -- first beta release
  6. */
  7.  
  8. #include "port.h"
  9.  
  10. // maximum number of mixer channels
  11. #define maxchan            8
  12.  
  13. static short            outputnumchan;            // number of mixer channels
  14. static int                outputblocksize;         // block size in samples
  15. static waveRate            outputrate;                // output sample rate
  16. static waveBits            outputbits;                // output bits per sample
  17. static waveSpeak        outputspeak;            // output number of speakers
  18. static short            outputsampsize;            // output bytes per sample
  19. static short            outputsampshift;        // lg(outputsampsize)
  20. static short            outputpaused;            // output paused flag
  21. static int                outputplayahead;        // number of blocks to keep in buf
  22. static int                outputremix;            // immediate remix flag
  23.  
  24. static mixCodec            mixcodecs[mixNumCodec];
  25. static int                numcodecs = 0;
  26.  
  27.  
  28. /* -------- WAVEFORM RENDERER --------
  29.     Copies samples, converting wave format (mono<->stereo, 8<->16),
  30.     temporal scaling (11kHz<->22kHz<->44kHz), and applying a mono or
  31.     stereo volume scale.  Code is described as macros to allow an
  32.     80-way unrolling of the main rendering loop.  This redundancy allows
  33.     the    compiler to produce optimized decisionless code specific to each
  34.     possible rendering task.
  35. */
  36.  
  37. // read source sample
  38. #define readsamp_s8_d8(i)                    \
  39.         i = *(unsigned char*)psrc;            \
  40.         psrc += sizeof(unsigned char);        \
  41.         i -= 0x80;                            
  42.  
  43. #define readsamp_s8_d16(i)                    \
  44.         i = *(unsigned char*)psrc;            \
  45.         psrc += sizeof(unsigned char);        \
  46.         i -= 0x80;                            \
  47.         i <<= 8;                            
  48.  
  49. #define readsamp_s16_d8(i)                    \
  50.         i = *(signed short*)psrc;            \
  51.         psrc += sizeof(signed short);        
  52.  
  53. #define readsamp_s16_d16(i)                    \
  54.         i = *(signed short*)psrc;            \
  55.         psrc += sizeof(signed short);        
  56.  
  57. #define readsamp(i,sb,db)                    \
  58.         readsamp_s ## sb ## _d ## db ## (i)
  59.  
  60. // apply volume scale
  61. #define scalesamp(i,vol)                    \
  62.         i *= vol.mul;                        \
  63.         i >>= vol.shift;
  64.  
  65. // normalize sample
  66. #define normsamp_s8_d8(i)                    \
  67.         i += 0x80;
  68.  
  69. #define normsamp_s8_d16(i)
  70.  
  71. #define normsamp_s16_d8(i)                    \
  72.         i >>= 8;                             \
  73.         i += 0x80;
  74.  
  75. #define normsamp_s16_d16(i)
  76.  
  77. #define normsamp(i,sb,db)                    \
  78.         normsamp_s ## sb ## _d ## db ## (i)
  79.  
  80. // write dest sample
  81. #define writesamp_d8(i)                                \
  82.         *(unsigned char*)pdst = (unsigned char) i;    \
  83.         pdst += sizeof(unsigned char);                
  84.  
  85. #define writesamp_d16(i)                            \
  86.         *(signed short*)pdst = (signed short) i;    \
  87.         pdst += sizeof(signed short);                
  88.  
  89. #define writesamp(i,db)                                \
  90.         writesamp_d ## db ## (i)
  91.  
  92. // mono output, stretching
  93. #define writedupmono_dup1(db)                        \
  94.         writesamp(i,db);
  95.  
  96. #define writedupmono_dup2(db)                        \
  97.         writesamp(i,db);                            \
  98.         writesamp(i,db);
  99.  
  100. #define writedupmono_dup4(db)                        \
  101.         writesamp(i,db);                            \
  102.         writesamp(i,db);                            \
  103.         writesamp(i,db);                            \
  104.         writesamp(i,db);
  105.  
  106. #define writedupmono(numdup,db)                        \
  107.         writedupmono_dup ## numdup ## (db)
  108.  
  109. // stereo output, stretching
  110. #define writedupstereo_dup1(db)                        \
  111.         writesamp(i,db); writesamp(j,db);
  112.  
  113. #define writedupstereo_dup2(db)                        \
  114.         writesamp(i,db); writesamp(j,db);            \
  115.         writesamp(i,db); writesamp(j,db);
  116.  
  117. #define writedupstereo_dup4(db)                        \
  118.         writesamp(i,db); writesamp(j,db);            \
  119.         writesamp(i,db); writesamp(j,db);            \
  120.         writesamp(i,db); writesamp(j,db);            \
  121.         writesamp(i,db); writesamp(j,db);                        
  122.  
  123. #define writedupstereo(numdup,db)                    \
  124.         writedupstereo_dup ## numdup ## (db)
  125.  
  126. // mono input, shrinking
  127. #define readavgmono_avg2(sb,db)                        \
  128.         readsamp(i,sb,db);                            \
  129.         readsamp(j,sb,db); i += j; i >>= 1;
  130.  
  131. #define readavgmono_avg4(sb,db)                        \
  132.         readsamp(i,sb,db);                            \
  133.         readsamp(j,sb,db); i += j;                    \
  134.         readsamp(j,sb,db); i += j;                    \
  135.         readsamp(j,sb,db); i += j; i >>= 2;
  136.  
  137. #define readavgmono(numavg,sb,db)                    \
  138.         readavgmono_avg ## numavg ## (sb,db)
  139.  
  140. // stereo input, shrinking
  141. #define readavgstereo_avg2(sb,db)                    \
  142.         readsamp(i,sb,db);                            \
  143.         readsamp(j,sb,db);                            \
  144.         readsamp(i1,sb,db); i += i1; i >>= 1;        \
  145.         readsamp(j1,sb,db); j += j1; j >>= 1;        
  146.  
  147. #define readavgstereo_avg4(sb,db)                    \
  148.         readsamp(i,sb,db);                            \
  149.         readsamp(j,sb,db);                            \
  150.         readsamp(i1,sb,db); i += i1;                \
  151.         readsamp(j1,sb,db); j += j1;                \
  152.         readsamp(i1,sb,db); i += i1;                \
  153.         readsamp(j1,sb,db); j += j1;                \
  154.         readsamp(i1,sb,db); i += i1; i >>= 2;        \
  155.         readsamp(j1,sb,db); j += j1; j >>= 2;
  156.  
  157. #define readavgstereo(numavg,sb,db)                    \
  158.         readavgstereo_avg ## numavg ## (sb,db)
  159.  
  160. // mono to mono copy
  161. #define monotomonodup(numdup,sb,db)            \
  162.     {                                        \
  163.         register int i;                        \
  164.         readsamp(i,sb,db)                    \
  165.         scalesamp(i,vol.both)                \
  166.         normsamp(i,sb,db)                    \
  167.         writedupmono(numdup,db)                \
  168.     }
  169.  
  170. #define monotomonoavg(numavg,sb,db)            \
  171.     {                                         \
  172.         register int i,j;                    \
  173.         readavgmono(numavg,sb,db);            \
  174.         scalesamp(i,vol.both);                \
  175.         normsamp(i,sb,db);                    \
  176.         writesamp(i,db);                    \
  177.     }
  178.  
  179. // mono to stereo copy
  180. #define monotostereodup(numdup,sb,db)        \
  181.     {                                        \
  182.         register int i,j;                    \
  183.         readsamp(i,sb,db)                    \
  184.         j = i;                                \
  185.         scalesamp(i,vol.left);                \
  186.         scalesamp(j,vol.right);                \
  187.         normsamp(i,sb,db)                    \
  188.         normsamp(j,sb,db)                    \
  189.         writedupstereo(numdup,db)            \
  190.     }
  191.  
  192. #define monotostereoavg(numavg,sb,db)        \
  193.     {                                        \
  194.         register int i,j;                    \
  195.         readavgmono(numavg,sb,db);            \
  196.         j = i;                                \
  197.         scalesamp(i,vol.left);                \
  198.         scalesamp(j,vol.right);                \
  199.         normsamp(i,sb,db);                    \
  200.         normsamp(j,sb,db);                    \
  201.         writesamp(i,db);                    \
  202.         writesamp(j,db);                    \
  203.     }                                                    
  204.  
  205. // stereo to mono copy
  206. #define stereotomonodup(numdup,sb,db)        \
  207.     {                                        \
  208.         register int i,j;                    \
  209.         readsamp(i,sb,db)                    \
  210.         readsamp(j,sb,db)                    \
  211.         scalesamp(i,vol.left)                \
  212.         scalesamp(j,vol.right)                \
  213.         i += j;                                \
  214.         i >>= 1;                            \
  215.         normsamp(i,sb,db)                    \
  216.         writedupmono(numdup,db);            \
  217.     }
  218.  
  219. #define stereotomonoavg(numavg,sb,db)        \
  220.     {                                        \
  221.         register int i,j,i1,j1;                \
  222.         readavgstereo(numavg,sb,db);        \
  223.         scalesamp(i,vol.left);                \
  224.         scalesamp(j,vol.right);                \
  225.         i += j;                                \
  226.         i >>= 1;                            \
  227.         normsamp(i,sb,db);                    \
  228.         writesamp(i,db);                    \
  229.     }                                                    
  230.  
  231. // stereo to stereo copy                
  232. #define stereotostereodup(numdup,sb,db)        \
  233.     {                                        \
  234.         register int i,j;                    \
  235.         readsamp(i,sb,db)                    \
  236.         readsamp(j,sb,db)                    \
  237.         scalesamp(i,vol.left)                \
  238.         scalesamp(j,vol.right)                \
  239.         normsamp(i,sb,db)                    \
  240.         normsamp(j,sb,db)                    \
  241.         writedupstereo(numdup,db);            \
  242.     }
  243.  
  244. #define stereotostereoavg(numavg,sb,db)        \
  245.     {                                        \
  246.         register int i,j,i1,j1;                \
  247.         readavgstereo(numavg,sb,db);        \
  248.         scalesamp(i,vol.left);                \
  249.         scalesamp(j,vol.right);                \
  250.         normsamp(i,sb,db);                    \
  251.         normsamp(j,sb,db);                    \
  252.         writesamp(i,db);                    \
  253.         writesamp(j,db);                    \
  254.     }
  255.  
  256. #define rendsamp(srcspeak,dstspeak,srcbits,dstbits,scaleop,scalefact)        \
  257.     srcspeak ## to ## dstspeak ## scaleop ## (scalefact,srcbits,dstbits)
  258.  
  259. // rendering loop
  260. #define rloop                  \
  261.     {                        \
  262.         while (numsamp)        \
  263.         {
  264. #define rloopend            \
  265.             numsamp--;        \
  266.         }                    \
  267.         break;                \
  268.     }
  269.  
  270. #define scaleswitch(sspeak,dspeak,sbits,dbits)                                    \
  271.     switch (scale) {                                                            \
  272.         case -4:    rloop rendsamp(sspeak,dspeak,sbits,dbits,avg,4); rloopend;    \
  273.         case -2:    rloop rendsamp(sspeak,dspeak,sbits,dbits,avg,2); rloopend;    \
  274.         case 1:        rloop rendsamp(sspeak,dspeak,sbits,dbits,dup,1); rloopend;    \
  275.         case 2:        rloop rendsamp(sspeak,dspeak,sbits,dbits,dup,2); rloopend;    \
  276.         case 4:        rloop rendsamp(sspeak,dspeak,sbits,dbits,dup,4); rloopend;    \
  277.     }
  278.  
  279. #define ifbits(srcspeak,dstspeak)                                         \
  280.     if (bitsrc == waveBits8)                                            \
  281.         if (bitdst == waveBits8) scaleswitch(srcspeak,dstspeak,8,8)        \
  282.         else scaleswitch(srcspeak,dstspeak,8,16)                        \
  283.     else                                                                 \
  284.         if (bitdst == waveBits8) scaleswitch(srcspeak,dstspeak,16,8)    \
  285.         else scaleswitch(srcspeak,dstspeak,16,16)                        
  286.  
  287. static void lowRender(pmem psrc, waveRate ratesrc, waveBits bitsrc, waveSpeak speaksrc,
  288.                       pmem pdst, waveRate ratedst, waveBits bitdst, waveSpeak speakdst,
  289.                       long numsamp, pmixVol pmv, int scale)
  290. /*
  291. this unrolls into:
  292.         4        number of speakers:        [mono|stereo] -> [mono|stereo]
  293.       * 4        number of sample bits:    [8|16] -> [8|16]
  294.       * 5        temporal scaling        [-4,-2,1,2,4]
  295.         = 80     separate rendering loops
  296.  
  297. in a hierarchy of five decisions (speaksrc,speakdst,bitsrc,bitdst,scale)
  298. */
  299. {
  300.     mixVol        vol;
  301.  
  302.     vol = *pmv;                                               
  303.  
  304.     if (speaksrc == waveSpeakMono)
  305.         if (speakdst == waveSpeakMono) ifbits(mono,mono)
  306.         else ifbits(mono,stereo)
  307.     else
  308.         if (speakdst == waveSpeakMono) ifbits(stereo,mono)
  309.         else ifbits(stereo,stereo)
  310.     return;
  311. }              
  312.  
  313. /* -------- DATA SOURCE -------- 
  314.     A stream of samples
  315. */
  316.  
  317. typedef enum
  318. {
  319.     dsrcTypeSilence,
  320.     dsrcTypeSample,
  321.     dsrcTypeCodec
  322. } dsrcType;
  323.  
  324. typedef struct
  325. {
  326.     short            sampscale;
  327.     short            sampshift;
  328.     pmem            pdata;
  329.     waveRate        rate;
  330.     waveBits        bits;
  331.     waveSpeak        speak;
  332.     mixVol            vol;
  333. } dsrcSample, *pdsrcSample;
  334.  
  335. typedef struct
  336. {
  337.     short            sampscale;
  338.     pmem            pdata;
  339.     waveRate        rate;
  340.     waveBits        bits;
  341.     waveSpeak        speak;
  342.     mixVol            vol;
  343.     /***/
  344. } dsrcCodec, *pdsrcCodec;
  345.  
  346. typedef union
  347. {
  348.     dsrcSample        sample;
  349.     dsrcCodec        codec;
  350. } dsrcUnion, *pdsrcUnion;
  351.  
  352. typedef struct
  353. {
  354.     dsrcType    type;
  355.     long        curpos;
  356.     long        remain;
  357.     dsrcUnion    u;
  358. } dsrc, *pdsrc;
  359.  
  360. static    mixVol        mixVolNorm = { {1,0},{1,0},{1,0} };
  361.  
  362. static void silenceRender(pmem pdest, long numsamp)
  363. {
  364.     long            num4, num1;
  365.     unsigned long    *plong;
  366.     unsigned char    *pchar;
  367.  
  368.     num1 = (numsamp << outputsampshift);
  369.     num4 = num1 >> 2;
  370.     num1 &= 3;
  371.     if (outputbits == waveBits8)
  372.     {
  373.         plong = (unsigned long*) pdest;
  374.         while (num4--) *plong++ = 0x80808080;
  375.         pchar = (unsigned char*) plong;
  376.         while (num1--) *pchar++ = 0x80;
  377.     }
  378.     else {
  379.         plong = (unsigned long*) pdest;
  380.         while (num4--) *plong++ = 0x00000000;
  381.         pchar = (unsigned char*) plong;
  382.         while (num1--) *pchar++ = 0x00;
  383.     }
  384.     return;
  385. }
  386.  
  387. static void sampleRender(pdsrcSample pds, long pos, long num, pmem pdest, pmixVol pmv)
  388. {
  389.     pmem    psrc;
  390.     long    numrendsrc;
  391.  
  392.     if (pds->sampscale > 0)
  393.     {
  394.         psrc = pds->pdata + ((pos/pds->sampscale) << pds->sampshift);
  395.         numrendsrc = num / pds->sampscale;
  396.         if (num % pds->sampscale) numrendsrc++;
  397.         lowRender(    psrc, pds->rate, pds->bits, pds->speak,
  398.                     pdest, outputrate, outputbits, outputspeak, 
  399.                     numrendsrc, pmv, (int)pds->sampscale);
  400.     }
  401.     else {
  402.         psrc = pds->pdata + ((-pos*pds->sampscale) << pds->sampshift);
  403.         numrendsrc = num * -pds->sampscale;
  404.         lowRender(    psrc, pds->rate, pds->bits, pds->speak,
  405.                     pdest, outputrate, outputbits, outputspeak, 
  406.                     num, pmv, (int)pds->sampscale);
  407.     }
  408.     return;
  409. }
  410.  
  411. static void codecRender(pdsrcCodec pdc, long pos, long num, pmem pdest, pmixVol pmv)
  412. {
  413.     /***/
  414. }
  415.  
  416. static long dsrcRender(pdsrc pds, pmem pdest, long numsamples, int cangrow, pmixVol pmv)
  417. {
  418.     long    numrend;
  419.  
  420.     if (cangrow && pds->type==dsrcTypeSilence && pds->remain < numsamples)
  421.         pds->remain = numsamples;
  422.     numrend = pds->remain;
  423.     if (numrend > numsamples) numrend = numsamples;
  424.     if (numrend)
  425.     {
  426.         switch (pds->type)
  427.         {
  428.             case dsrcTypeSilence:
  429.                 silenceRender(pdest, numrend);
  430.                 break;
  431.             case dsrcTypeSample:
  432.                 sampleRender(&pds->u.sample, pds->curpos, numrend, pdest, pmv);
  433.                 break;
  434.             case dsrcTypeCodec:
  435.                 codecRender(&pds->u.codec, pds->curpos, numrend, pdest, pmv);
  436.                 break;
  437.         }
  438.         pds->curpos += numrend;
  439.         pds->remain -= numrend;
  440.     }
  441.     return numrend;
  442. }
  443.  
  444. static dsrcType dsrcCreate(pdsrc pds, pmixSound pms)
  445. {
  446.     if (!pms) {
  447.         pds->type = dsrcTypeSilence;
  448.         pds->remain = 0;
  449.         pds->curpos = 0;
  450.         return dsrcTypeSilence;
  451.     }
  452.     else if (pms->type == mixCodecPCM)
  453.     {
  454.         pdsrcSample psamp = &pds->u.sample;
  455.         long        numsamp;
  456.  
  457.         psamp->pdata = pms->pdata;
  458.         psamp->rate = pms->rate;
  459.         psamp->speak = pms->speak;
  460.         psamp->bits = pms->bits;
  461.         psamp->vol = pms->vol;
  462.         switch (psamp->speak * psamp->bits)
  463.         {
  464.             case 1:    psamp->sampshift = 0; break;
  465.             case 2: psamp->sampshift = 1; break;
  466.             case 4: psamp->sampshift = 2; break;
  467.         }
  468.         if (psamp->rate <= outputrate) {
  469.             psamp->sampscale = (short)outputrate / (short)psamp->rate;
  470.             numsamp = pms->samples * psamp->sampscale;
  471.         }
  472.         else  {
  473.             psamp->sampscale = -(short)psamp->rate / (short)outputrate;
  474.             numsamp = pms->samples / -psamp->sampscale;
  475.         }
  476.         pds->remain = numsamp;
  477.         pds->curpos = 0;
  478.         pds->type = dsrcTypeSample;
  479.         return dsrcTypeSample;
  480.     }
  481.     else {
  482.         /***/
  483.         pds->type = dsrcTypeCodec;
  484.         return dsrcTypeCodec;
  485.     }
  486. }
  487.  
  488. static long dsrcRewind(pdsrc pds, long numsamples)
  489. {
  490.     if (pds->curpos >= numsamples) 
  491.     {
  492.         pds->remain += numsamples;
  493.         pds->curpos -= numsamples;
  494.     }
  495.     else {
  496.         numsamples = pds->curpos;
  497.         pds->remain += numsamples;
  498.         pds->curpos = 0;
  499.     }
  500.     return numsamples;
  501. }
  502.  
  503. static void dsrcDestroy(pdsrc pds)
  504. {
  505.     if (pds->type == dsrcTypeCodec)
  506.     {
  507.         /***/
  508.     }
  509.     return;
  510. }
  511.  
  512. static long dsrcGetCurPos(pdsrc pds)
  513. {
  514.     return pds->curpos;
  515. }
  516.  
  517. static long dsrcGetNumSamples(pdsrc pds)
  518. {
  519.     return pds->curpos + pds->remain;
  520. }
  521.  
  522. static long dsrcGetCurRemain(pdsrc pds)
  523. {
  524.     return pds->remain;
  525. }
  526.  
  527. static void dsrcTrim(pdsrc pds, long maxrewind)
  528. {
  529.     if (pds->type == dsrcTypeCodec)
  530.     {
  531.         /***/
  532.     }
  533.     return;
  534. }
  535.  
  536. static void dsrcTruncate(pdsrc pds)
  537. {
  538.     pds->remain = 0;
  539.     if (pds->type == dsrcTypeCodec)
  540.     {
  541.         /***/
  542.     }
  543.     return;
  544. }
  545.  
  546. static int dsrcContainsPtr(pdsrc pds, pmem p)
  547. {
  548.     switch (pds->type)
  549.     {
  550.         case dsrcTypeSilence:
  551.             return 0;
  552.         case dsrcTypeSample:
  553.             if (p == pds->u.sample.pdata) return 1;
  554.             return 0;
  555.         case dsrcTypeCodec:
  556.             if (p == pds->u.codec.pdata) return 1;
  557.             return 0;
  558.     }
  559.     return 0;
  560. }
  561.  
  562. static void dsrcGetVol(pdsrc pds, pmixVol pv)
  563. {
  564.     switch (pds->type)
  565.     {
  566.         case dsrcTypeSilence:
  567.             *pv = mixVolNorm;
  568.             break;
  569.         case dsrcTypeSample:
  570.             *pv = pds->u.sample.vol;
  571.             break;
  572.         case dsrcTypeCodec:
  573.             *pv = pds->u.codec.vol;
  574.             break;
  575.     }
  576.     return;
  577. }
  578.  
  579. /* -------- CHANNEL LIST --------
  580.     An array of doublely-linked lists.
  581. */
  582.  
  583.  
  584. typedef struct _tagcnode *pcnode;
  585.  
  586. typedef struct _tagcnode
  587. {
  588.     dsrcType    type;
  589.     dsrc        ds;
  590.     pcnode        pnext;
  591.     pcnode        pprev;
  592. } cnode;
  593.  
  594. typedef struct
  595. {
  596.     pcnode        pfirst;
  597.     pcnode        plast;
  598.     pcnode        pcur;
  599.     mixVol        curvol;
  600.     mixVol        vol;
  601. } channel, *pchannel;
  602.  
  603. static channel        chan[maxchan];
  604.  
  605. static void chanInit()
  606. {
  607.     pcnode        pcn;
  608.     pchannel    pchan;
  609.     short        i;
  610.  
  611.     pchan = chan;
  612.     for (i=0; i<outputnumchan; i++)
  613.     {
  614.         pcn = (pcnode) memNew(sizeof(cnode));
  615.         pcn->type = dsrcTypeSilence;
  616.         dsrcCreate(&pcn->ds, 0);
  617.         pcn->pnext = pcn->pprev = 0;
  618.         pchan->pfirst = pchan->plast = pchan->pcur = pcn;
  619.         pchan->vol = pchan->curvol = mixVolNorm;
  620.         pchan++;
  621.     }
  622.     return;
  623. }
  624.  
  625. static void chanFree()
  626. {
  627.     short    i;
  628.     pcnode    pcn, pcnnext;
  629.  
  630.     for (i=0; i<outputnumchan; i++)
  631.     {
  632.         pcn = chan[i].pfirst;
  633.         while (pcn)
  634.         {
  635.             pcnnext = pcn->pnext;
  636.             dsrcDestroy(&pcn->ds);
  637.             memDispose((pmem)pcn);
  638.             pcn = pcnnext;
  639.         }
  640.     }
  641.     return;
  642. }
  643.  
  644. static void chanVerify(short channum, short arerewound)
  645. {
  646.     pchannel    pchan;
  647.     pcnode        pcur, pprev;
  648.     int            foundcur, lastsil;
  649.     long        totsiz;
  650.     long        cursize;
  651.  
  652.     pchan = chan + channum;
  653.     pcur = pchan->pfirst;
  654.     pprev = 0;
  655.     foundcur = 0;
  656.     totsiz = 0;
  657.     lastsil = 0;
  658.     while (pcur) {           
  659.         if (pcur->type == dsrcTypeSilence)
  660.         {
  661.             if (lastsil) portFatalError(badlog, 0);
  662.             lastsil = 1;
  663.         } else lastsil = 0;
  664.  
  665.         cursize = dsrcGetNumSamples(&pcur->ds);
  666.         if (!arerewound)
  667.             if (cursize != dsrcGetCurPos(&pcur->ds) && pcur->pnext)
  668.                 portFatalError(badlog, 0);
  669.         totsiz += cursize;
  670.  
  671.         if (pcur == pchan->pcur) {
  672.             if (foundcur) portFatalError(badlog, 0);
  673.             foundcur = 1;
  674.         }
  675.  
  676.         if (pcur->pprev != pprev) portFatalError(badlog, 0);
  677. //        if (!cursize && pcur->pnext) portFatalError(badlog, 0);
  678.         if (cursize < 0) portFatalError(badlog, 0);
  679.         pprev = pcur;
  680.         pcur = pcur->pnext;
  681.     }
  682.  
  683.     if (pprev != pchan->plast) portFatalError(badlog, 0);
  684.     if (!foundcur) portFatalError(badlog, 0);
  685.     if (!arerewound && pchan->pcur != pchan->plast) portFatalError(badlog, 0);
  686.  
  687.     return;
  688. }
  689.  
  690. static void chanVerifyAll(short arerewound)
  691. {
  692.     short    c;
  693.  
  694.     for (c=0; c<outputnumchan; c++)
  695.         chanVerify(c, arerewound);
  696.     return;
  697. }
  698.  
  699. static void chanTrim(short channum)
  700. {
  701.     pcnode        pcur, pnext;
  702.     long        maxsamples, siz;
  703.     pchannel    pchan;
  704.  
  705.     chanVerify(channum, 0);
  706.     maxsamples = (long)outputblocksize * (long)outputplayahead;
  707.     pchan = chan + channum;
  708.     pcur = pchan->pcur;
  709.     siz = dsrcGetCurPos(&pchan->pcur->ds);
  710.     siz -= dsrcGetNumSamples(&pchan->pcur->ds);
  711.     while (1) {
  712.         siz += dsrcGetNumSamples(&pchan->pcur->ds);
  713.         if (siz >= maxsamples) break;
  714.         pcur = pcur->pprev;
  715.         if (!pcur) break;
  716.     }
  717.     if (pcur) {
  718.         pchan->pfirst = pcur;
  719.         pnext = pcur->pprev;
  720.         pcur->pprev = 0;
  721.         pcur = pnext;
  722.     }
  723.     while (pcur) {
  724.         pnext = pcur->pprev;
  725.         dsrcDestroy(&pcur->ds);
  726.         memDispose((pmem)pcur);
  727.         pcur = pnext;
  728.     }
  729.     dsrcTrim(&pchan->pcur->ds, maxsamples);
  730.     chanVerify(channum, 0);
  731.     return;
  732. }
  733.  
  734. static void chanSetVol(short channum, pmixVol pmv)
  735. {
  736.     pchannel    pchan;
  737.     mixVol        v;
  738.  
  739.     chanVerify(channum, 1);
  740.     pchan = chan + channum;
  741.     if (pmv)
  742.         pchan->vol = *pmv;
  743.     dsrcGetVol(&pchan->pcur->ds, &v);
  744.     mixVolMult(&pchan->curvol, &pchan->vol, &v);
  745.     chanVerify(channum, 1);
  746.     return;
  747. }
  748.  
  749. static void chanRender(pmem pdest, short channum, long numsamp)
  750. {
  751.     pchannel    pchan;
  752.     pcnode        pcur;
  753.     long        numrend;
  754.     int            cangrow;
  755.  
  756.     chanVerify(channum, 1);
  757.     pchan = chan + channum;
  758.     pcur = pchan->pcur;
  759.     if (numsamp >0)
  760.         while (1)
  761.         {
  762.             cangrow = (pcur->pnext == 0);
  763.             numrend = dsrcRender(&pcur->ds, pdest, numsamp, cangrow, &pchan->curvol);
  764.             if (numrend != numsamp)
  765.                 if (!pcur->pnext)
  766.                 {
  767.                     pcur->pnext = (pcnode) memNew(sizeof(cnode));
  768.                     pcur->pnext->pprev = pcur;
  769.                     pcur = pcur->pnext;
  770.                     pchan->plast = pchan->pcur = pcur;
  771.                     pcur->pnext = 0;
  772.                     pcur->type = dsrcCreate(&pcur->ds, 0);
  773.                 }
  774.                 else pcur = pcur->pnext;
  775.             numsamp -= numrend;
  776.             if (numsamp <= 0) break;
  777.             pdest += (numrend << outputsampshift);
  778.         }
  779.     chanVerify(channum, 0);
  780.     return;
  781. }
  782.  
  783. static void chanRewind(short channum, long numsamples)
  784. {
  785.     pchannel    pchan;
  786.     pcnode        pcur;
  787.     long        rewind, rewound;
  788.     int            innew;
  789.  
  790.     pchan = chan + channum;
  791.     rewind = numsamples;
  792.     pcur = pchan->pcur;
  793.     innew = 0;
  794.     while (rewind > 0)
  795.     {
  796.         rewound = dsrcRewind(&pcur->ds, rewind);
  797.         if (rewound != rewind)
  798.         {
  799.             pcur = pcur->pprev;
  800.             pchan->pcur = pcur;
  801.             if (!pcur) portFatalError(badlog, 0);
  802.             innew = 1;
  803.         }
  804.         rewind -= rewound;
  805.     }
  806.     chanVerify(channum, 1);
  807.     if (innew) chanSetVol(channum, 0);
  808.     return;
  809. }
  810.  
  811. static void chanTruncate(short channum)
  812. {
  813.     pcnode        plast, pcur;
  814.     pchannel    pchan;
  815.  
  816.     pchan = chan + channum;
  817.     plast = pchan->plast;
  818.     pcur = pchan->pcur;
  819.     while (plast != pcur)
  820.     {
  821.         pchan->plast = plast->pprev;
  822.         dsrcDestroy(&plast->ds);
  823.         memDispose((pmem)plast);
  824.         plast = pchan->plast;
  825.         if (!plast) portFatalError(badlog, 0);
  826.     }
  827.     plast->pnext = 0;
  828.     dsrcTruncate(&plast->ds);
  829.     chanVerify(channum, 0);
  830.     return;
  831. }
  832.  
  833. static void chanAddSound(short channum, pmixSound pms)
  834. {
  835.     pchannel    pchan;
  836.     pcnode        psamp, plast;
  837.  
  838.     pchan = chan + channum;
  839.     plast = pchan->plast;
  840.     psamp = (pcnode) memNew(sizeof(cnode));
  841.     pchan->plast = psamp;
  842.     psamp->pprev = plast;
  843.     plast->pnext = psamp;
  844.     psamp->type = dsrcCreate(&psamp->ds, pms);
  845.     psamp->pnext = 0;
  846.     if (!dsrcGetCurRemain(&pchan->pcur->ds))
  847.         pchan->pcur = psamp;
  848.     chanVerify(channum, 0);
  849.     return;
  850. }
  851.  
  852. static short chanFindData(pmem pdata)
  853. {
  854.     short        i;
  855.     pchannel    pchan;
  856.     pcnode        pcur;
  857.  
  858.     for (i=0; i<outputnumchan; i++)
  859.     {
  860.         pchan = chan + i;
  861.         pcur = pchan->pfirst;
  862.         while (pcur) 
  863.         {                       
  864.             if (dsrcContainsPtr(&pcur->ds, pdata)) return i;
  865.             pcur = pcur->pnext;
  866.         }
  867.     }
  868.     return -1;
  869. }
  870.  
  871. static short chanIsSilent(short channum)
  872. {
  873.     pchannel    pchan;
  874.  
  875.     pchan = chan + channum;
  876.     if (pchan->pfirst != pchan->plast) return 0;
  877.     if (pchan->pcur != pchan->pfirst) portFatalError(badlog, 0);
  878.     if (pchan->pcur->type == dsrcTypeSilence) return 1;
  879.     return 0;
  880. }
  881.  
  882. /* -------- 8 BIT MIXER FUNCTION ARRAY -------- 
  883.     An array of functions that mix samples
  884. */
  885.  
  886. #define mixer8func(name)                                                 \
  887.     static void name (    unsigned char *psrc, unsigned char *pdest,         \
  888.                         long numsamples)                                \
  889.     {                                                                    \
  890.         int                i;                                                \
  891.         while (numsamples)                                                 \
  892.         {                                                                \
  893.             i  = *psrc;
  894. #define mixer8add(num)                                                     \
  895.             i += *(psrc + mixRingSize*(long)num);                        
  896. #define mixer8store(numchan)                                            \
  897.             i -= (numchan-1) << 7;                                         \
  898.             *pdest++ = (unsigned char) i;                                \
  899.             psrc++; numsamples--;                                        \
  900.         }                                                                \
  901.         return;                                                            \
  902.     }
  903.  
  904. mixer8func(mix8_1)    mixer8store(1)
  905. mixer8func(mix8_2)    mixer8add(1) mixer8store(2)
  906. mixer8func(mix8_3)    mixer8add(1) mixer8add(2) mixer8store(3)
  907. mixer8func(mix8_4)    mixer8add(1) mixer8add(2) mixer8add(3) mixer8store(4)
  908. mixer8func(mix8_5)    mixer8add(1) mixer8add(2) mixer8add(3) mixer8add(4) 
  909.                     mixer8store(5)
  910. mixer8func(mix8_6)    mixer8add(1) mixer8add(2) mixer8add(3) mixer8add(4) 
  911.                     mixer8add(5) mixer8store(6)
  912. mixer8func(mix8_7)    mixer8add(1) mixer8add(2) mixer8add(3) mixer8add(4) 
  913.                     mixer8add(5) mixer8add(6) mixer8store(7)
  914. mixer8func(mix8_8)    mixer8add(1) mixer8add(2) mixer8add(3) mixer8add(4) 
  915.                     mixer8add(5) mixer8add(6) mixer8add(7) mixer8store(8)
  916.  
  917. typedef void (*mixer8fn)(unsigned char *, unsigned char *, long);
  918.  
  919. mixer8fn    mix8[maxchan]=    {
  920.                                 mix8_1, mix8_2, mix8_3, mix8_4,
  921.                                 mix8_5, mix8_6, mix8_7, mix8_8
  922.                             };
  923.  
  924.  
  925. /* -------- 16 BIT MIXER FUNCTION ARRAY -------- 
  926.      An array of functions that mix samples
  927. */
  928.  
  929. #define mixer16func(name)                                                 \
  930.     static void name (    signed short *psrc, signed short *pdest,         \
  931.                         long numsamples)                                \
  932.     {                                                                    \
  933.         int                i;                                                \
  934.         while (numsamples)                                                 \
  935.         {                                                                \
  936.             i  = *psrc;
  937. #define mixer16add(num)                                                 \
  938.             i += *(psrc + mixRingSize*(long)num/2L);
  939. #define mixer16store                                                     \
  940.             *pdest++ = (signed short) i;                                \
  941.             psrc++; numsamples--;                                        \
  942.         }                                                                \
  943.         return;                                                            \
  944.     }
  945.  
  946. mixer16func(mix16_1)    mixer16store
  947. mixer16func(mix16_2)    mixer16add(1) mixer16store
  948. mixer16func(mix16_3)    mixer16add(1) mixer16add(2) mixer16store
  949. mixer16func(mix16_4)    mixer16add(1) mixer16add(2) mixer16add(3) mixer16store
  950. mixer16func(mix16_5)    mixer16add(1) mixer16add(2) mixer16add(3) mixer16add(4) 
  951.                         mixer16store
  952. mixer16func(mix16_6)    mixer16add(1) mixer16add(2) mixer16add(3) mixer16add(4) 
  953.                         mixer16add(5) mixer16store
  954. mixer16func(mix16_7)    mixer16add(1) mixer16add(2) mixer16add(3) mixer16add(4) 
  955.                         mixer16add(5) mixer16add(6) mixer16store
  956. mixer16func(mix16_8)    mixer16add(1) mixer16add(2) mixer16add(3) mixer16add(4) 
  957.                         mixer16add(5) mixer16add(6) mixer16add(7) mixer16store
  958.  
  959. typedef void (*mixer16fn)(signed short *, signed short *, long);
  960.  
  961. mixer16fn    mix16[maxchan]= {
  962.                                 mix16_1, mix16_2, mix16_3, mix16_4,
  963.                                 mix16_5, mix16_6, mix16_7, mix16_8
  964.                             };
  965.  
  966.  
  967. /* -------- MIX RING ARRAY --------
  968.     This data structure is an array of ring buffers.  There is one ring
  969.     buffer per mixer channel.  The ring buffer holds samples that have
  970.     been scaled to the destination wave format and channel volume.  A 
  971.     current position pointer points to the next sample to be mixed.  Start 
  972.     and end pointers point to the first and last valid samples in the buffer.
  973.     One size counter indicates the total number of samples in the buffer 
  974.     (end minus start), the other indicates    the total number of unmixed 
  975.     samples in the buffer (end minus current).  
  976.  
  977.        +-----------------------------------------------------+
  978.        |xxxxxxxxxxxxDATADATADATADATADATADATADATADATAxxxxxxxxx|
  979.        +-----------------------------------------------------+
  980.         ^           ^                   ^           ^        ^
  981.         |            |                    |            |           |
  982.         (begin)     (first)                (cur)        (last)     (end)
  983. */
  984.  
  985. static    pmem        pringbegin;                // beginning of ring buffer (all)
  986. static    pmem        pringend;                // end of ring buffer (all)
  987. static    pmem        pringcur;                // current position in ring buffer
  988. static    pmem        pringfirst;                // beginning of ring buffer data
  989. static    pmem        pringlast;                // end of ring buffer data
  990. static    long        ringremain;                // number of samples remaining
  991. static    long        ringtotal;                // total samples in buffer
  992. static    mixSound    ringnewsound[maxchan];    // sound to mix
  993. static    short        ringisnewsound[maxchan];// sound to mix flag
  994. static    short        ringnumnewsound;        // number of sounds to mix
  995. static    long        remixtimesound;            // total ms rerendering sounds
  996. static    long        remixtimemix;            // total ms remixing ring buffer
  997. static    short        remixtimenumsound;        // number of sounds rerendered
  998. static    short        remixtimenummix;        // number of ring buffer remixes
  999.  
  1000. static void mrInit()
  1001. {
  1002.     pmem        pmem;
  1003.     short    i;
  1004.  
  1005.     // allocate ring buffers
  1006.     pmem = memNew(mixRingSize * (long)outputnumchan);
  1007.     // initialize ring buffer, set to empty
  1008.     ringtotal = ringremain = 0;
  1009.     pringbegin = pringfirst = pringlast = pringcur = pmem;
  1010.     pringend = pmem + mixRingSize;
  1011.     // clear new sound array
  1012.     for (i=0; i<outputnumchan; i++) ringisnewsound[i] = 0;
  1013.     ringnumnewsound = 0;
  1014.     remixtimesound = 0;
  1015.     remixtimenumsound = 0;
  1016.     remixtimemix = 0;
  1017.     remixtimenummix = 0;
  1018.     return;
  1019. }                        
  1020.  
  1021. static void mrFree()
  1022. {
  1023.     // dispose of ring buffers
  1024.     memDispose(pringbegin);
  1025.     return;
  1026. }
  1027.  
  1028.  
  1029. static void mrRenderAll(long numsamples)
  1030. {
  1031.     long    del;
  1032.     long    siz;
  1033.     short    i;
  1034.  
  1035.     del = numsamples - ringremain;
  1036.     if (del > 0)
  1037.     {
  1038.         ringtotal += del;
  1039.         ringremain += del;
  1040.  
  1041.         siz = (pringend - pringlast) >> outputsampshift;
  1042.         if (siz > del) siz = del;
  1043.         for (i=0; i<outputnumchan; i++)
  1044.             chanRender(pringlast + mixRingSize*i, i, siz);
  1045.         pringlast += (siz << outputsampshift);
  1046.         if (pringlast >= pringend) pringlast = pringbegin;
  1047.  
  1048.         del -= siz;
  1049.         if (del > 0)
  1050.         {
  1051.             for (i=0; i<outputnumchan; i++)
  1052.                 chanRender(pringlast + mixRingSize*i, i, del);
  1053.             pringlast += (del << outputsampshift);
  1054.         }
  1055.  
  1056.         del = ringtotal - (mixRingSize >> outputsampshift);
  1057.         if (del > 0)
  1058.         {
  1059.             ringtotal -= del;
  1060.             pringfirst += (del << outputsampshift);
  1061.             if (pringfirst >= pringend) pringfirst -= mixRingSize;
  1062.         }
  1063.  
  1064.         for (i=0; i<outputnumchan; i++)
  1065.             chanTrim(i);
  1066.     }
  1067.     return;
  1068. }
  1069.  
  1070. static void mrReRender(short channum, long numsamp)
  1071. {
  1072.     long    size1;
  1073.  
  1074.     size1 = (pringend - pringcur) >> outputsampshift;
  1075.     if (size1 > numsamp) size1 = numsamp;
  1076.     chanRender(pringcur + mixRingSize * channum, channum, size1);
  1077.     numsamp -= size1;
  1078.     if (numsamp > 0)
  1079.         chanRender(pringbegin + mixRingSize * channum, channum, numsamp);
  1080.     return;
  1081. }
  1082.  
  1083. static void mrLowMix(pmem pdest, long numsamp)
  1084. {
  1085.     switch (outputbits)
  1086.     {
  1087.         case waveBits8:
  1088.             mix8[outputnumchan-1]((unsigned char*)pringcur, (unsigned char*)pdest, 
  1089.                 numsamp * outputspeak);
  1090.             break;
  1091.         case waveBits16:
  1092.             mix16[outputnumchan-1]((signed short*)pringcur, (signed short*)pdest, 
  1093.                 numsamp * outputspeak);
  1094.             break;
  1095.     }
  1096.     pringcur += (numsamp << outputsampshift);
  1097.     if (pringcur > pringend) portFatalError(badlog, 0);
  1098.     if (pringcur == pringend) pringcur = pringbegin;
  1099.     ringremain -= numsamp;
  1100.     return;
  1101. }
  1102.  
  1103. static void mrMix(short remix)
  1104. {
  1105.     long    samplesplaying;
  1106.     long    origsamplesplaying;
  1107.     long    newsamplesplaying;
  1108.     long    samplestomix;
  1109.     short    blockstofill;
  1110.     pmem    pdest;
  1111.     short    i;
  1112.  
  1113.     if (outputpaused) return;
  1114.  
  1115.     waveGetSampleCount(&samplesplaying);
  1116.     origsamplesplaying = samplesplaying;
  1117.  
  1118.     if (remix) {
  1119.         if (remixtimenummix)
  1120.         {
  1121.             samplesplaying -= (remixtimemix / remixtimenummix);
  1122.             if (remixtimenumsound && ringnumnewsound)
  1123.                 samplesplaying -= (remixtimesound / remixtimenumsound) * 
  1124.                     ringnumnewsound;
  1125.             if (samplesplaying < 0) samplesplaying = 0;
  1126.         }
  1127.         ringremain += samplesplaying;
  1128.         pringcur -= (samplesplaying << outputsampshift);
  1129.         if (pringcur < pringbegin) pringcur += mixRingSize;
  1130.     }
  1131.  
  1132.     if (ringnumnewsound)
  1133.     {
  1134.         for (i=0; i<outputnumchan; i++)
  1135.         {
  1136.             if (ringisnewsound[i])
  1137.             {
  1138.                 chanRewind(i, ringremain);
  1139.                 chanTruncate(i);        
  1140.                 if (ringnewsound[i].pdata)
  1141.                     chanAddSound(i, ringnewsound + i);
  1142.                 mrReRender(i, ringremain);
  1143.                 ringisnewsound[i] = 0;
  1144.             }
  1145.         }
  1146.         if (remix) {
  1147.             waveGetSampleCount(&newsamplesplaying);
  1148.             remixtimesound += (origsamplesplaying - newsamplesplaying);
  1149.             remixtimenumsound += ringnumnewsound;
  1150.             origsamplesplaying = newsamplesplaying;
  1151.         }
  1152.         ringnumnewsound = 0;
  1153.     }
  1154.  
  1155.     if (remix)
  1156.         blockstofill = outputplayahead;
  1157.     else {                        
  1158.         blockstofill = 0;
  1159.         while (samplesplaying <= outputblocksize * outputplayahead)
  1160.         {
  1161.             samplesplaying += outputblocksize;
  1162.             blockstofill++;
  1163.         }
  1164.         blockstofill--;
  1165.     }
  1166.  
  1167.     if (blockstofill > 0)
  1168.     {
  1169.         mrRenderAll(outputblocksize * blockstofill);
  1170.         while (blockstofill)
  1171.         {                             
  1172.             waveGetPlayPtr(&pdest);
  1173.             samplestomix = (pringend - pringcur) >> outputsampshift;
  1174.             if (samplestomix > ringremain) samplestomix = ringremain;
  1175.             if (samplestomix > outputblocksize) samplestomix = outputblocksize;
  1176.             mrLowMix(pdest, samplestomix);
  1177.             pdest += (samplestomix << outputsampshift);
  1178.             samplestomix = outputblocksize - samplestomix;
  1179.             if (samplestomix) mrLowMix(pdest, samplestomix);
  1180.        
  1181.             if (remix) {
  1182.                 waveGetSampleCount(&newsamplesplaying);
  1183.                 remixtimemix += (origsamplesplaying - newsamplesplaying);
  1184.                 remixtimenummix++;
  1185.                 remix = 0;
  1186.                 waveReset();
  1187.             }
  1188.             wavePlay();
  1189.             blockstofill--;
  1190.         }    
  1191.     }
  1192.  
  1193.     if (remixtimenummix >= 128)
  1194.     {
  1195.         remixtimemix = remixtimemix * 32L / remixtimenummix;
  1196.         remixtimenummix = 32;
  1197.     }
  1198.     if (remixtimenumsound >= 128)
  1199.     {
  1200.         remixtimesound = remixtimesound * 32L / remixtimenumsound;
  1201.         remixtimenumsound = 32;
  1202.     }
  1203.     if (remixtimesound < 0) remixtimesound = 0;
  1204.     if (remixtimemix < 0) remixtimemix = 0;
  1205.  
  1206.     if (ringremain != 0) portFatalError(badlog, 0);
  1207.     return;
  1208. }
  1209.  
  1210. void mrNewSound(short channum, pmixSound pms)
  1211. {
  1212.     ringnewsound[channum] = *pms;
  1213.     if (!ringisnewsound[channum]) ringnumnewsound++;
  1214.     ringisnewsound[channum] = 1;
  1215.     return;
  1216. }
  1217.  
  1218.  
  1219. /* -------- PUBLIC FUNCTIONS -------- */
  1220.  
  1221. rescode    mixOpen(short numchan, waveSpeak ns, waveRate pr, waveBits pb)
  1222. {
  1223.     outputnumchan = numchan;
  1224.     outputpaused = 0;
  1225.     outputrate = pr;
  1226.     outputbits = pb;
  1227.     outputspeak = ns;
  1228.     if (waveOpen(pr,pb,ns, &outputblocksize, &outputplayahead, 
  1229.             &outputremix)) return badlog;
  1230.     outputsampsize = (short)pb * (short)ns;
  1231.     switch (outputsampsize)
  1232.     {
  1233.         case 1:
  1234.             outputsampshift = 0;
  1235.             break;
  1236.         case 2:
  1237.             outputsampshift = 1;
  1238.             break;
  1239.         case 4:
  1240.             outputsampshift = 2;
  1241.             break;
  1242.     }
  1243.     mrInit();
  1244.     chanInit();
  1245.     chanVerifyAll(0);
  1246.     mixPump();
  1247.     chanVerifyAll(0);
  1248.     return 0;
  1249. }
  1250.  
  1251. rescode    mixClose()
  1252. {
  1253.     chanVerifyAll(0);
  1254.     waveClose();
  1255.     mrFree();
  1256.     chanFree();
  1257.     return 0;
  1258. }
  1259.  
  1260. rescode    mixPlay(short chan, mixSound *pmix)
  1261. {
  1262.     chanVerifyAll(0);
  1263.     if (pmix->samples <= 0) return 0;
  1264.     mrNewSound(chan, pmix);
  1265.     chanVerifyAll(0);
  1266.     if (outputremix) mrMix(1);
  1267.     chanVerifyAll(0);
  1268.     return 0;
  1269. }
  1270.  
  1271. rescode    mixUnplay(pmem pdata)
  1272. {
  1273.     short    chan;
  1274.  
  1275.     chanVerifyAll(0);
  1276.     chan = chanFindData(pdata);
  1277.     if (chan == -1) return 0;
  1278.     mixSilence(chan);
  1279.     chanVerifyAll(0);
  1280.     return 0;
  1281. }    
  1282.  
  1283. rescode    mixAppend(short chan, mixSound *pmix)
  1284. {
  1285.     chanVerifyAll(0);
  1286.     if (pmix->samples <= 0) return 0;
  1287.     if (outputremix && chanIsSilent(chan))
  1288.     {
  1289.         mrNewSound(chan, pmix);
  1290.         chanVerifyAll(0);
  1291.         mrMix(1);
  1292.     }
  1293.     else {
  1294.         chanAddSound(chan, pmix);
  1295.         chanVerifyAll(0);
  1296.         mrMix(0);
  1297.     }
  1298.     chanVerifyAll(0);
  1299.     return 0;
  1300. }
  1301.  
  1302. rescode    mixSilence(short chan)
  1303. {
  1304.     mixSound   ms;
  1305.  
  1306.     chanVerifyAll(0);
  1307.     ms.pdata = 0;
  1308.     mrNewSound(chan, &ms);
  1309.     chanVerifyAll(0);
  1310.     if (outputremix) mrMix(1);
  1311.     chanVerifyAll(0);
  1312.     return 0;
  1313. }
  1314.  
  1315. rescode mixIsSilent(short chan)
  1316. {
  1317.     chanVerifyAll(0);
  1318.     return chanIsSilent(chan);
  1319. }
  1320.  
  1321. rescode    mixLoadChannel(short chan, pmixSound *pmix, short num)
  1322. {
  1323.     /***/
  1324.     return 0;
  1325. }
  1326.  
  1327. rescode    mixSetVolume(short chan, pmixVol vol)
  1328. {
  1329.     chanVerifyAll(0);
  1330.     chanSetVol(chan, vol);
  1331.     chanVerifyAll(0);
  1332.     if (outputremix) mrMix(1);
  1333.     chanVerifyAll(0);
  1334.     return 0;
  1335. }
  1336.  
  1337. rescode mixGetVolume(short c, pmixVol pvol)
  1338. {
  1339.     chanVerifyAll(0);
  1340.     *pvol = chan[c].vol;
  1341.     return 0;    
  1342. }
  1343.  
  1344. rescode    mixIsDataPlaying(pmem pdata)
  1345. {
  1346.     short    chan;
  1347.  
  1348.     chanVerifyAll(0);
  1349.     chan = chanFindData(pdata);
  1350.     if (chan == -1) return 0;
  1351.     return 1;
  1352. }
  1353.  
  1354. rescode    mixPause()
  1355. {
  1356.     chanVerifyAll(0);
  1357.     outputpaused = 1;
  1358.     return 0;
  1359. }
  1360.  
  1361. rescode    mixResume()
  1362. {
  1363.     chanVerifyAll(0);
  1364.     outputpaused = 0;
  1365.     return 0;
  1366. }
  1367.  
  1368. rescode    mixPump()
  1369. {
  1370.     chanVerifyAll(0);
  1371.     mrMix(0);
  1372.     chanVerifyAll(0);
  1373.     return 0;
  1374. }
  1375.  
  1376. rescode    mixVolCreate(pmixVol pmv, double vleft, double vright)
  1377. {
  1378.     double    vboth;
  1379.  
  1380.     if (vleft < 1.0)
  1381.     {
  1382.         pmv->left.mul = (long) (vleft * 65536.0);
  1383.         pmv->left.shift = 16;
  1384.     }
  1385.     else if (vleft == 1.0)
  1386.     {
  1387.         pmv->left.mul = 1;
  1388.         pmv->left.shift = 0;
  1389.     }
  1390.     else {
  1391.         pmv->left.mul = (long) (vleft * 256.0);
  1392.         pmv->left.shift = 8;
  1393.     }
  1394.     if (vright < 1.0)
  1395.     {
  1396.         pmv->right.mul = (long) (vright * 65536.0);
  1397.         pmv->right.shift = 16;
  1398.     }
  1399.     else if (vright == 1.0)
  1400.     {
  1401.         pmv->right.mul = 1;
  1402.         pmv->right.shift = 0;
  1403.     }
  1404.     else {
  1405.         pmv->right.mul = (long) (vright * 256.0);
  1406.         pmv->right.shift = 8;
  1407.     }
  1408.     vboth = (vleft + vright) / (double)2.0;
  1409.     if (vboth < 1.0)
  1410.     {
  1411.         pmv->both.mul = (long) (vboth * 65536.0);
  1412.         pmv->both.shift = 16;
  1413.     }
  1414.     else if (vboth == 1.0)
  1415.     {
  1416.         pmv->both.mul = 1;
  1417.         pmv->both.shift = 0;
  1418.     }
  1419.     else {
  1420.         pmv->both.mul = (long) (vboth * 256.0);
  1421.         pmv->both.shift = 8;
  1422.     }
  1423.     return 0;
  1424. }
  1425.  
  1426. #define mixVolSingle(dest, s1, s2)                                 \
  1427.     {                                                            \
  1428.         double    f1,f2,fd;                                        \
  1429.         f1 = (double)(s1).mul / (double)(1L << (s1).shift);        \
  1430.         f2 = (double)(s2).mul / (double)(1L << (s2).shift);        \
  1431.         fd = f1 * f2;                                            \
  1432.         if (fd < 1.0) {                                            \
  1433.             (dest).mul = (long) (fd * 65536.0);                    \
  1434.             (dest).shift = 16;                                    \
  1435.         }                                                        \
  1436.         else if (fd == 1.0) {                                    \
  1437.             (dest).mul = 1;                                        \
  1438.             (dest).shift = 0;                                    \
  1439.         }                                                        \
  1440.         else {                                                    \
  1441.             (dest).mul = (long) (fd * 256.0);                    \
  1442.             (dest).shift = 8;                                    \
  1443.         }                                                        \
  1444.     }
  1445.  
  1446. rescode mixVolMult(pmixVol pmvDest, pmixVol pmvsrc1, pmixVol pmvsrc2)
  1447. {
  1448.     mixVolSingle(pmvDest->left, pmvsrc1->left, pmvsrc2->left);
  1449.     mixVolSingle(pmvDest->right, pmvsrc1->right, pmvsrc2->right);
  1450.     mixVolSingle(pmvDest->both, pmvsrc1->both, pmvsrc2->both);
  1451.     return 0;
  1452. }
  1453.  
  1454. rescode    mixInstallCodec(pmixCodec pmc)
  1455. {
  1456.     int        i;
  1457.  
  1458.     for (i=0; i<numcodecs; i++) 
  1459.         if (mixcodecs[i].type == pmc->type) return 1;
  1460.     mixcodecs[numcodecs] = *pmc;
  1461.     numcodecs++;
  1462.     return 0;
  1463. }
  1464.  
  1465.